package com.ywger.web.config.restetemplate;
import com.ywger.integration.config.restemplate.RestTemplateProperties;
import com.ywger.integration.resttemplate.inteceptor.RestHeaderInterceptor;
import com.ywger.integration.resttemplate.inteceptor.RestLogInterceptor;
import com.ywger.integration.resttemplate.inteceptor.RestRespErrorHandler;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.client.BufferingClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chenmeng
 * @date 2021-07-17 13:56
 * @desc
 */
@Configuration
public class RestTemplateConfig {

    @Autowired
    private RestTemplateProperties properties;

    @Bean
    public RestTemplate restTemplate() {
        //将RequestFactory换成BufferingClientHttpRequestFactory方便从多次读取response,日志拦截类中需读取response 流
        RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(clientHttpRequestFactory()));
        List<ClientHttpRequestInterceptor> interceptors=new ArrayList<ClientHttpRequestInterceptor>();
        interceptors.add(new RestLogInterceptor());
        interceptors.add(new RestHeaderInterceptor());
        restTemplate.setInterceptors(interceptors);
        restTemplate.setErrorHandler(new RestRespErrorHandler());
        //设置编码格式
        StringHttpMessageConverter converter = new StringHttpMessageConverter(StandardCharsets.UTF_8) {
            @Override
            protected MediaType getDefaultContentType(String outOrderNumber) throws IOException {
                return MediaType.APPLICATION_JSON;
            }
        };
        restTemplate.getMessageConverters().add(0, converter);
        return restTemplate;
    }

    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory() {
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        clientHttpRequestFactory.setHttpClient(httpClientBuilder().build());
        // 连接超时时间/毫秒
        clientHttpRequestFactory.setConnectTimeout(properties.getConnectionTimeOut());
        // 读写超时时间/毫秒
        clientHttpRequestFactory.setReadTimeout(properties.getReadTimeOut());
        // 请求超时时间/毫秒
        clientHttpRequestFactory.setConnectionRequestTimeout(properties.getConnectionRequestTimeOut());
//        simpleClientHttpRequestFactory.setProxy(proxy);
        return clientHttpRequestFactory;
    }

    @Bean
    public HttpClientBuilder httpClientBuilder() {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        httpClientBuilder.setConnectionManager(poolingConnectionManager());
        httpClientBuilder.setKeepAliveStrategy(((httpResponse, httpContext) -> properties.getKeepAliveTime()));
        return httpClientBuilder;
    }

    @Bean
    public HttpClientConnectionManager poolingConnectionManager() {
        PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
        //MaxTotal 连接池最大连接数
        poolingConnectionManager.setMaxTotal(properties.getMaxTotal());
        //DefaultMaxPerRoute  每个主机的并发
        poolingConnectionManager.setDefaultMaxPerRoute(properties.getMaxPerRoute());
        //每个主机的并发 ValidateAfterInactivity
        // 可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间，如果超过，释放socket重新建立
        //poolingConnectionManager.setValidateAfterInactivity(30000);
        return poolingConnectionManager;
    }
}
